package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.article.dto.*;
import com.heima.article.entity.*;
import com.heima.article.feign.BehaviorClient;
import com.heima.article.feign.UserClient;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.util.AppThreadLocalUtil;
import com.netflix.hystrix.Hystrix;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 文章信息表，存储已发布的文章 服务实现类
 * </p>
 *
 * @author mcm
 * @since 2022-08-10
 */
@Service
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements IApArticleService {

    @Autowired
    IApArticleContentService contentService;

    @Autowired
    @Lazy
    IPublishService publishService;

    @Autowired
    IApCollectionService collectionService;

    @Autowired(required = false)
    KafkaTemplate<String,String> kafkaTemplate;

    @Autowired
    BehaviorClient behaviorClient;

    @Autowired
    UserClient userClient;

    @Autowired
    IApAuthorService authorService;

    @Autowired
    StringRedisTemplate redisTemplate;

    //保存或者修改文章
    @Override
    public ResponseResult<Long> saveArticle(ArticleDto dto) {
        ApArticle article = new ApArticle();
        BeanUtils.copyProperties(dto,article);
        //判断是否存在id
        if (dto.getId() == null) {
            //不存在id，新增文章，新增文章内容
            article.setCreatedTime(new Date());
            this.save(article);
            //保存文章内容
            ApArticleContent content = new ApArticleContent();
            content.setArticleId(article.getId());
            content.setContent(dto.getContent());
            contentService.save(content);

            //创建文章的静态页面 使用异步线程执行
            publishService.createHtml(article,dto.getContent());

            return ResponseResult.okResult(article.getId());
        }
        //存在id，修改文章，修改文章内容
        this.updateById(article);
        //修改文章内容
        LambdaUpdateWrapper<ApArticleContent> update = new LambdaUpdateWrapper<>();
        //update ap_article_content set content = ? where article_id = ?
        update.eq(ApArticleContent::getArticleId,dto.getId());
        update.set(ApArticleContent::getContent,dto.getContent());
        contentService.update(update);
        return ResponseResult.okResult(article.getId());
    }

    /**
     * 加载文章列表
     * @param dto
     * @param type 0：最新 1：更多
     * @return
     */
    @Override
    public ResponseResult load(ArticleHomeDto dto, int type) {
        //判断是否是首页，如果是首页加载文章，先查询redis中的缓存数据
        if (dto.getLoaddir() == 1) {
            //如果redis中缓存存在，直接返回文章数据
            String key = "hot_article_" + dto.getChannelId();
            Set<String> strings = redisTemplate.opsForZSet().reverseRange(key, 0, dto.getSize() - 1);
            //将json转换成文章对象
            List<ApArticle> articles = new ArrayList<>();
            for (String string : strings) {
                ApArticle article = JSON.parseObject(string, ApArticle.class);
                articles.add(article);
            }
            if (articles.size() == dto.getSize()) {
                return ResponseResult.okResult(articles);
            }
            //否则还走原来的数据库查询逻辑


        }
        //定义分页条件
        IPage<ApArticle> pageParam = new Page<>(1,dto.getSize());
        //定义查询条件
        LambdaQueryWrapper<ApArticle> qw = new LambdaQueryWrapper<>();
        //如果频道id不为0，添加频道id查询
        if (dto.getChannelId() != 0) {
            qw.eq(ApArticle::getChannelId,dto.getChannelId());
        }
        //如果是加载更多文章，需要判断文章的发布时间小于前端传递的最小时间
        if (type == 1) {
            qw.lt(ApArticle::getPublishTime,dto.getMinTime());
        } else {
            //如果是加载最新文章，需要判断文章的发布时间大于前端传递的最大时间
           qw.gt(ApArticle::getPublishTime,dto.getMaxTime());
        }
        //文章的状态不能是已下架和删除
        qw.eq(ApArticle::getIsDelete,false);
        qw.eq(ApArticle::getIsDown,false);
        //文章按照发布顺序倒叙排列
        qw.orderByDesc(ApArticle::getPublishTime);
        //分页查询
        IPage<ApArticle> iPage = this.page(pageParam, qw);
        return ResponseResult.okResult(iPage.getRecords());
    }


    //加载文章详情
    @Override
    public ResponseResult loadArticleInfo(ArticleInfoDto dto) {
        //根据id查询文章
        ApArticle article = this.getById(dto.getArticleId());
        //根据id查询文章内容
        LambdaUpdateWrapper<ApArticleContent> qw = new LambdaUpdateWrapper<>();
        qw.eq(ApArticleContent::getArticleId,dto.getArticleId());
        ApArticleContent articleContent = contentService.getOne(qw);
        ArticleVo vo = new ArticleVo();
        vo.setConfig(article);
        vo.setContent(articleContent);
        return ResponseResult.okResult(vo);
    }

    //收藏文章
    @Override
    public ResponseResult collect(CollectionBehaviorDto dto) {
        //构建ApCollection
        User user = AppThreadLocalUtil.get();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        ApCollection apCollection = new ApCollection();
        apCollection.setEntryId(user.getUserId());
        apCollection.setArticleId(dto.getArticleId());
        apCollection.setCollectionTime(new Date());
        LambdaQueryWrapper<ApCollection> qw = new LambdaQueryWrapper<>();
        qw.eq(ApCollection::getEntryId,user.getUserId());
        qw.eq(ApCollection::getArticleId,dto.getArticleId());
        if (dto.getOperation() == 0) {
            //查询历史记录
            int count = collectionService.count(qw);
            if (count == 0) {
                collectionService.save(apCollection);
                sendMessage(dto.getArticleId(),1,3);
            }
        } else {
            //取消收藏
            boolean remove = collectionService.remove(qw);
            if (remove) {
                sendMessage(dto.getArticleId(),-1,3);
            }
        }
        return ResponseResult.okResult();
    }

    //加载行为记录
    @Override
    public ResponseResult loadBehavior(ArticleInfoDto dto) {
        boolean isfollow = false;
        boolean islike = false;
        boolean isunlike = false;
        boolean iscollection = false;

        User user = AppThreadLocalUtil.get();

        //查询点赞记录
        LikesBehaviorDto likeDto = new LikesBehaviorDto();
        likeDto.setArticleId(dto.getArticleId());
        if (user != null) {
            likeDto.setUserId(user.getUserId());
        } else {
            likeDto.setEquipmentId(dto.getEquipmentId());
        }
        ResponseResult<ApLikesBehavior> likesBehaviorResponseResult = behaviorClient.getLikes(likeDto);
        if (likesBehaviorResponseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
            ApLikesBehavior likesBehavior = likesBehaviorResponseResult.getData();
            if (likesBehavior != null) {
                islike = true;
            }
        }
        //查询不喜欢记录
        UnLikesBehaviorDto unlikeDto = new UnLikesBehaviorDto();
        unlikeDto.setArticleId(dto.getArticleId());
        if (user != null) {
            unlikeDto.setUserId(user.getUserId());
        } else {
            unlikeDto.setEquipmentId(dto.getEquipmentId());
        }
        ResponseResult<ApUnlikesBehavior> unlikesBehaviorResponseResult = behaviorClient.getUnLikes(unlikeDto);
        if (likesBehaviorResponseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
            ApUnlikesBehavior unlikesBehavior = unlikesBehaviorResponseResult.getData();
            if (unlikesBehavior != null) {
                isunlike = true;
            }
        }
        //查询收藏记录
        LambdaQueryWrapper<ApCollection> qw = new LambdaQueryWrapper<>();
        qw.eq(ApCollection::getEntryId,user.getUserId());
        qw.eq(ApCollection::getArticleId,dto.getArticleId());
        ApCollection one = collectionService.getOne(qw);
        if (one != null) {
            iscollection = true;
        }
        //查询关注记录
        if (user != null) {
            FollowBehaviorDto followDto = new FollowBehaviorDto();
            followDto.setUserId(user.getUserId());
            ApAuthor apAuthor = authorService.getById(dto.getAuthorId());
            followDto.setFollowId(apAuthor.getUserId());
            ResponseResult<ApUserFollow> followResponseResult = userClient.getFollow(followDto);
            if (followResponseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
                ApUserFollow userFollow = followResponseResult.getData();
                if (userFollow != null) {
                    isfollow = true;
                }
            }
        }
        Map<String,Boolean> map = new HashMap<>();
        map.put("isfollow",isfollow);
        map.put("islike",islike);
        map.put("isunlike",isunlike);
        map.put("iscollection",iscollection);
        return ResponseResult.okResult(map);
    }

    private void sendMessage(Long articleId, int add,int type) {
        UpdateArticleMessage message = new UpdateArticleMessage();
        message.setArticleId(articleId);
        message.setType(type);
        message.setAdd(add);
        String data = JSON.toJSONString(message);
        kafkaTemplate.send(articleBehaviorTopic, data);
    }

    @Value("${topic.articleBehaviorTopic}")
    private String articleBehaviorTopic;
}
